/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/* 
 * Copyright (c) 2009 City University of Hong Kong
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License m_version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Author: Wilson Thong (wilsonwk@ee.cityu.edu.hk) 
 */

#ifndef BMSN_GENERATOR_H
#define BMSN_GENERATOR_H

#include <string>
#include "jitter-sim-include.h"
#include "bmsn-topology.h"

// number of neighbors of each node in a BMSN topology
#define NUM_NBR 4
// the default number of rows for a generated BMSN topology
#define DEFAULT_N_ROWS 5
// The m_version number of the BmsnGenerator class
#define BMSN_GENERATOR_VER "1.0.0.0"
// The maximum number of nodes that can be generated by the generator.
// NodeId being set to MAX_N_NODES means that it is to be isolated and 
// not to be connected with any links
#define MAX_N_NODES (1000*1000)

using namespace std;
//using namespace ns3;

namespace ns3 {
namespace eecityu {

/**
 * \brief generate a Bidirectional Manhattan Street Network (BMSN) topology
 *
 * \see BmsnTopology
 */
class BmsnGenerator : public Object
{
public:
  static TypeId GetTypeId (void);
  /**
   * Generate a square BMSN on a 2-dimensional hyper-cube. Default number of m_nodes = 100
   * and links' bandwidth are 1 Mbps.
   */
  BmsnGenerator (void);
  /**
   * \deprecated Use BmsnGenerator::Generate ( BmsnTopology & ) instead.
   * 
   * \brief Generate a BMSN topology 
   *
   * Generate a set of nodes and a set of links such that they are interconnected according
   * to BMS topology on a 2-dimensional hyper-cube.
   */
  void Generate (void);
  /**
   * \brief Generate a BMSN topology and update a BmsnTopology object accordingly.
   *
   * \param bmsnNet An BmsnTopology to hold the generated BMSN topology
   * 
   * Generate a set of nodes and a set of links such that they are interconnected according
   * to BMS topology on a 2-dimensional hyper-cube.
   */
  void Generate ( BmsnTopology& bmsnNet );

private:
  ///**
  // * \param nodeId The id of a node
  // * \returns Warp around the nodeId if it is out of the valid range
  // * [0, m_nRows*m_nRows).
  // */
  //uint32_t NodeIdAdjust (uint32_t nodeId);

  /**
   * \brief Generate a BMSN topology and update the node and 
   * net device containers accordingly
   *
   * \param nodes Contain all nodes of the generated BMSN topology
   * \param devices Contain all devices of the generated BMSN topology
   * 
   * Generate a set of nodes and a set of links such that they are 
   * interconnected according to BMS topology on a 2-dimensional hyper-cube.
   */
  void Generate ( NodeContainer& nodes, NetDeviceContainer& devices );
  /**
   * \brief Get the first octet of the network number in the IP address
   * assigned to the generated BMSN network
   *
   * \return The first octet of the network number
   */
  uint32_t GetFirstOctetNetId ();

  /// Propagation delay for all links
  Time m_delay;
  /// Line speed for all links
  DataRate m_bps;
  /// The maximum number of packets all queues can take
  uint32_t m_queueMaxPackets;

  /// number of m_nodes
  uint32_t m_nRows;
  /// The first octet of the network number of the generated BMSN network
  uint32_t m_firstOctetNetId;
  /// the m_version number of this class
  static string m_version;
};

/**
 * \todo June 10, 2009 Write the implementation codes
 *
 * \brief Help walking on a BMSN topology
 *
 * It provides methods to get a correct node ID when walking on a BMSN node
 * to its north neighbor, east neighbor, south neighbor, and west neighbor.
 */
class BmsnWalkingHelper {
public:
  /**
   * \brief Construct a helper object to help walking on nodes in a BMSN topology
   *
   * \param here The current node from which the walk starts. Default is 0
   */
  BmsnWalkingHelper (uint32_t here = 0);
  /**
   * \brief Set the number of nodes of the BMSN topology on which this
   * class is walking
   */
  void setNRows (uint32_t nRows);
  /**
   * \brief Set the node from where the walk starts
   * 
   * \param here The node ID from where the walk starts
   */
  void setHere (uint32_t here);
  /**
   * \brief Get the node over which currently this class is on
   *
   * \return The current node ID
   */
  uint32_t getHere ();
  /**
   * \return Return the node ID of the north neighbor, and go to there
   */
  uint32_t GoNorth ();
  /**
   * \return Return the node ID of the east neighbor, and go to there
   */
  uint32_t GoEast  ();
  /**
   * \return Return the node ID of the south neighbor, and go to there
   */
  uint32_t GoSouth ();
  /**
   * \return Return the node ID of the west neighbor, and go to there
   */
  uint32_t GoWest  ();

private:
  /// Remember a node ID of the current location
  uint32_t m_here;
  /// The number of rows in a BMSN topology
  uint32_t m_nRows;
};

} // namespace eecityu
} // namespace ns3


#endif /* BMSN_GENERATOR_H */
